package org.xx.armory.spring5.mvc;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.CacheControl;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.concurrent.TimeUnit;

import static org.springframework.http.HttpHeaders.CACHE_CONTROL;
import static org.xx.armory.spring5.mvc.WebUtils.getFullPath;

public class OutputCacheInterceptor
        implements HandlerInterceptor {
    private final Logger logger = LoggerFactory.getLogger(OutputCacheInterceptor.class);

    public void postHandle(
            HttpServletRequest request,
            HttpServletResponse response,
            Object handler,
            ModelAndView modelAndView
    )
            throws Exception {
        if (response.getStatus() == HttpServletResponse.SC_OK && handler instanceof HandlerMethod) {
            if (this.logger.isTraceEnabled()) {
                logger.trace("Add output cache to {}", getFullPath(request));
            }

            final var outputCache = ((HandlerMethod) handler).getMethodAnnotation(OutputCache.class);
            final CacheControl cc;
            if (outputCache != null) {
                switch (outputCache.directive()) {
                    case PUBLIC:
                        cc = CacheControl.maxAge(outputCache.maxAge(), TimeUnit.SECONDS).cachePublic().mustRevalidate();
                        break;
                    case PRIVATE:
                        cc = CacheControl.maxAge(outputCache.maxAge(), TimeUnit.SECONDS).cachePrivate().mustRevalidate();
                        break;
                    default:
                        cc = CacheControl.noStore().mustRevalidate();
                        break;
                }
            } else {
                cc = CacheControl.noStore().mustRevalidate();
            }

            response.setHeader(CACHE_CONTROL, cc.getHeaderValue());
        }
    }
}
